package org.reborn.engine.render.texture

import org.reborn.utils.niobuffer.BufferUtil
import org.reborn.utils.FileUtil

import java.nio.{Buffer,ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,FloatBuffer,LongBuffer,DoubleBuffer}

import javax.media.opengl.{GL,GL2,GL2GL3,GL2ES2}
import javax.imageio.ImageIO
import java.awt.image.{BufferedImage,Raster}
import java.awt.Image

/**
 * Base trait for various types of OpenGL textures
 * 
 * @define imagesDescription An array of Buffers that specify the image(s) used to create the texture.
 * The texture requires at least one Buffer, but more may be specified to create mipmaps. 
 * The first Buffer corresponds to the zeroth mipmap, and each Buffer afterwards corresponds to the next
 * mipmap level. If more than one Buffer is specified, it will override the auto-mipmapping setting from 
 * the metadata.
 */
trait Texture {
  val metadata:TextureMetadata
  private var glPixelFormat:Int = 0
  private var glDataType:Int = 0

  /**
   * A function that sets the image data in a texture. This method is
   * specific to a specific type of texture (1D, 2D, CubeMap, etc...)
   * 
   * This function basically wraps a call to glTextureImage*D
   * 
   * @param gl reference to the GL object
   * @param images a Seq of java.nio.Buffers that contains the image data.
   * @param glFormat the GL format of the image data (GL_RGB, GL_RGBA, GL_LUMINANCE, etc...)
   * @param glType the GL type of the image data (GL_UNSIGNED_BYTE, GL_FLOAT, etc...)
   */
  protected def setImageData(gl:GL, images:Seq[Buffer], glFormat:Int, glType:Int)
  
  
  /**
   * Creates a new OpenGL texture from a by array representing the image data.
   * @param images $imagesDescription
   * @param glFormat the GL format of the image data (GL_RGB, GL_RGBA, GL_LUMINANCE, etc...).
   * @param glType the GL type of the image data (GL_UNSIGNED_BYTE, GL_FLOAT, etc...).
   */
  def createTexture(gl:GL, images:Seq[Buffer], glFormat:Int, glType:Int){
	this.glPixelFormat = glFormat
	this.glDataType = glType
	
	//Generate a GL texture name/id
	val arr = new Array[Int](1)
	gl.glGenTextures(1, arr, 0)
	metadata.glId = arr(0)
	
	//Bind the new texture ID to its target (1D, 2D, CubeMap, etc...)
	bind(gl)

	//Do any additional OpenGL texture commands as defined
	//by the types of metadata that have been mixed in
	metadata.doTexParameterCommands(gl)
	
	//Set the image data in the texture
	setImageData(gl,images,glFormat,glType)
  }
  
  /**
   * Deletes this texture from GL graphics memory
   * @param gl
   */
  def deleteTexture(gl:GL){
	val arr = new Array[Int](1)
	arr(0) = metadata.glId
	gl.glDeleteTextures(1, arr, 0)
  }
  
  /**
   * Binds this texture id so that OpenGL will use it for texture operations
   * @param gl
   */
  def bind(gl:GL){
	gl.glBindTexture(metadata.glTarget,metadata.glId)
  }
  
  /**
   * @return The GL data type of the image data. (GL_UNSIGNED_BYTE, GL_INT, etc...)
   */
  def glType:Int = glDataType
  
  /**
   * @return The GL format of the pixel data in the texture (GL_RGB, GL_RGBA, GL_LUMINANCE, etc...)
   */
  def glFormat:Int = glPixelFormat
}

object Texture{
  
  
}